package lowijs.XfDroid;

import static lowijs.XfDroid.XfDroidConstants.*;
import static lowijs.XfDroid.FriendDBAdapter.*;
import com.googlecode.xfdroid.R;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Set;
import java.util.TreeSet;

import lowijs.XfireClient.XfireObserver;
import lowijs.XfireClient.event.EventManager;
import lowijs.XfireClient.event.ToastEvent;
import lowijs.XfireClient.event.XfireEvent;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.ContentObserver;
import android.database.Cursor;
import android.graphics.Color;
import android.graphics.Typeface;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import android.text.Editable;
import android.text.SpannableStringBuilder;
import android.text.TextWatcher;
import android.text.style.ForegroundColorSpan;
import android.text.style.StyleSpan;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CursorAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class ConvoWindow extends Activity implements XfireObserver {
	private SimpleDateFormat TIME_FORMAT;

	private Button btSend = null;

	private EditText etMessage = null;

	private SharedPreferences prefs = null;

	private int skin = R.layout.android_convoline;

	private Cursor cursor;

	private Cursor members;

	private long channelid;

	private Set<Long> online;

	private ListView lv;

	class UserMonitor extends Handler {
		@Override
		public void dispatchMessage(Message msg) {
			members.requery();
			while (members.moveToNext()) {
				long id = members.getLong(0);

				if (members.getInt(1) == FriendDBAdapter.ONLINE_FLAG) {
					if (online.add(Long.valueOf(id))) {
						online(id);
					}
				} else if (online.remove(Long.valueOf(id))) {
					offline(id);
				}
			}
		}
	}

	private Handler toastHandler = new Handler() {
		public void handleMessage(Message m) {
			String message = (String)m.obj;
			Toast t = Toast.makeText(getBaseContext(), message, 2);
			t.show();
		}
	};

	public void onCreate(Bundle b) {
		super.onCreate(b);

		TIME_FORMAT = new SimpleDateFormat(getString(R.string.convo_time_format));

		setContentView(R.layout.convowindow);

		btSend = (Button)findViewById(R.id.btSend);
		etMessage = (EditText)findViewById(R.id.etMessage);

		channelid = getIntent().getExtras().getLong(KEY_CHANNEL_ID);
		FriendDBAdapter db = FriendDBAdapter.getInstance(getApplicationContext());
		cursor = db.channel(channelid);
		members = db.channelMembers(channelid);
		startManagingCursor(cursor);
		members.registerContentObserver(new ContentObserver(new UserMonitor()) {
		});

		online = new TreeSet<Long>();

		String title = getString(R.string.convo_window_title);
		setTitle(title.replace(ARG_0, db.channelname(channelid)));

		lv = (ListView)findViewById(R.id.lvConversation);
		lv.setDividerHeight(0);

		// Classic
		//lv.setAdapter(new SimpleCursorAdapter(this, R.layout.convoline, cursor, new String[] {FriendDBAdapter.KEY_NICKNAME, FriendDBAdapter.KEY_MESSAGE, FriendDBAdapter.KEY_POSTED}, new int[] {R.id.tvNickname, R.id.tvMessage, R.id.tvTime}));

		// Android
		lv.setAdapter(new CursorAdapter(this, cursor) {
			@Override
			public View newView(Context context, Cursor cursor, ViewGroup parent) {
				return View.inflate(context, skin, null);
			}

			@Override
			public void bindView(View view, Context context, Cursor cursor) {
				if (skin == R.layout.android_convoline) {
					TextView tv = (TextView)view;
					SpannableStringBuilder builder = new SpannableStringBuilder();
					String nickname = cursor.getString(cursor.getColumnIndex(FriendDBAdapter.KEY_NICKNAME));
					String message = cursor.getString(cursor.getColumnIndex(FriendDBAdapter.KEY_MESSAGE));
					int imindex = cursor.getInt(cursor.getColumnIndex(FriendDBAdapter.KEY_IMINDEX));

					if (imindex == -9999) {
						int stid = R.string.convo_user_offline;

						if (message.trim().toLowerCase().equals(IS_NOW_ONLINE)) {
							stid = R.string.convo_user_online;
						}

						String status = getString(stid);

						builder.append(status.replace(ARG_0, nickname));
						builder.setSpan(new ForegroundColorSpan(Color.BLUE), 0, builder.length(), 0);
						builder.setSpan(new StyleSpan(Typeface.BOLD), 0, builder.length(), 0);
					} else {
						int ns = builder.length();
						builder.append(nickname).append(MESSAGE_DEVIDER);
						int ne = builder.length();
						builder.append(message);
						builder.setSpan(new StyleSpan(Typeface.BOLD), ns, ne, 0);
					}

					int position = cursor.getPosition();
					view.setBackgroundResource((position&1)==0 ? R.drawable.android_chat_even: R.drawable.android_chat_odd);
					tv.setText(builder);
				} else {
					String nickname = cursor.getString(cursor.getColumnIndex(FriendDBAdapter.KEY_NICKNAME));
					String message = cursor.getString(cursor.getColumnIndex(FriendDBAdapter.KEY_MESSAGE));
					int imindex = cursor.getInt(cursor.getColumnIndex(FriendDBAdapter.KEY_IMINDEX));
					long posted = cursor.getLong(cursor.getColumnIndex(FriendDBAdapter.KEY_POSTED));

					TextView tvTime = (TextView)view.findViewById(R.id.tvTime);
					TextView tvNickname = (TextView)view.findViewById(R.id.tvNickname);
					TextView tvMessage = (TextView)view.findViewById(R.id.tvMessage);

					if (imindex == -9999) {
						SpannableStringBuilder builder = new SpannableStringBuilder();
						int stid = R.string.convo_user_offline;

						if (message.trim().toLowerCase().equals(IS_NOW_ONLINE)) {
							stid = R.string.convo_user_online;
						}

						String status = getString(stid);

						builder.append(status.replace(ARG_0, nickname));
						builder.setSpan(new ForegroundColorSpan(Color.BLUE), 0, builder.length(), 0);
						builder.setSpan(new StyleSpan(Typeface.BOLD), 0, builder.length(), 0);

						tvMessage.setVisibility(View.GONE);
						tvNickname.setText(builder);
						tvNickname.setTextSize(tvTime.getTextSize());
					} else {
						tvMessage.setText(message);
						tvNickname.setText(nickname);
					}

					Date date = new Date(posted);
					tvTime.setText(TIME_FORMAT.format(date));
				}
			}
		});

		View.OnClickListener sendListener = new View.OnClickListener() {
			public void onClick(View v) {
				sendIM();
			}
		};
		btSend.setOnClickListener(sendListener);

		TextView.OnEditorActionListener actionListener =
			new TextView.OnEditorActionListener() {
				public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
					if (etMessage.length() != 0 && prefs.getBoolean(PREF_SEND_ON_ENTER, true)) {
						sendIM();
					}

					return true;
				}
			};

		TextWatcher textWatcher = new TextWatcher() {
			public void onTextChanged(CharSequence s, int start, int before,
					int count) {
					btSend.setEnabled(s.length() != 0);
			}
			
			public void beforeTextChanged(CharSequence s, int start, int count,
					int after) {
				
			}
			
			public void afterTextChanged(Editable s) {
				
			}
		};	
		
		etMessage.setOnEditorActionListener(actionListener);
		etMessage.addTextChangedListener(textWatcher);
		etMessage.requestFocus();
		
		prefs = PreferenceManager.getDefaultSharedPreferences(this);
	}

	protected void offline(long rowid) {
		if (prefs.getBoolean(PREF_CONVO_NOTIFY, true)) {
			FriendDBAdapter.getInstance(getApplicationContext()).notify(channelid, rowid, false);
		}
	}

	protected void online(long rowid) {
		if (prefs.getBoolean(PREF_CONVO_NOTIFY, true)) {
			FriendDBAdapter.getInstance(getApplicationContext()).notify(channelid, rowid, true);
		}
	}

	public void onResume() {
		super.onResume();
	}

	private void setSkin(int skin) {
		if (this.skin != skin) {
			this.skin = skin;

			if (skin == R.layout.android_convoline) {
				lv.setBackgroundColor(Color.WHITE);
			} else {
				lv.setBackgroundColor(Color.BLACK);
			}
		}
	}
	
	public void onStart() {
		super.onStart();
		XfDroidService.sendNoNotificationsFor(channelid);
		EventManager.addObserver(this);

		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
		if (prefs.getString(PREF_THEME, PREF_THEME_DEFAULT).equals(PREF_THEME_ANDROID)) {
			setSkin(R.layout.android_convoline);
		} else {
			setSkin(R.layout.convoline);
		}

		online.clear();
		members.requery();
		while (members.moveToNext()) {
			if (members.getInt(1) == FriendDBAdapter.ONLINE_FLAG) {
				online.add(Long.valueOf(members.getLong(0)));
			}
		}
	}
	
	public void onPause() {
		super.onPause();
	}
	
	public void onStop() {
		super.onStop();
		XfDroidService.sendNoNotificationsFor(-1);
		EventManager.removeObserver(this);
		members.deactivate();
	}

	public void onDestroy() {
		super.onDestroy();
		cursor.close();
		members.close();
	}

	private void sendIM() {
		EditText etMessage = (EditText)findViewById(R.id.etMessage);

		try {
			String text = etMessage.getText().toString();
			etMessage.setText(EMPTY_STRING);

			if (text.trim().length() == 0) {
			} else if (!XfDroidService.sendIM(channelid, text)) {
				Toast.makeText(getApplicationContext(), getString(R.string.convo_user_currently_offline), Toast.LENGTH_SHORT).show();
			}
		} catch (IOException e) {
			Toast.makeText(getApplicationContext(), getString(R.string.convo_you_currently_offline), Toast.LENGTH_SHORT).show();
		}
	}
	
	public void handleEvent(XfireEvent event) {
		switch(event.getEventType()) {
		case XfireEvent.XF_DCREASON:
			setResult(RESULT_CANCELED, new Intent(this, Login.class));
			finish();
			return;
		case XfireEvent.XF_TOAST:
			ToastEvent toast = (ToastEvent)event;
			Message message = new Message();
			message.obj = toast.getMessage();
			toastHandler.sendMessage(message);
			return;
		}
	}
}
